/*
 * @Author: 杰编程 2306248989@qq.com
 * @Date: 2023-08-07 15:10:16
 * @LastEditors: 杰编程 2306248989@qq.com
 * @LastEditTime: 2023-08-07 20:26:42
 * @FilePath: /lesson26/NetCacul/TcpServer.hpp
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 */
#pragma once

#include "Sock.hpp"
#include "Protocol.hpp"
#include <iostream>
#include <string>
#include <pthread.h>
#include <functional>

namespace tcpserver_ns
{
    using namespace protocol_ns;
    const uint16_t defaultPort = 8888;
    using func_t = std::function<Response(const Request &)>;

    class tcp_server;
    struct pthreadData
    {
        pthreadData(tcp_server *ts, int sockfd, std::string clientip, uint16_t clientport)
            : _ts(ts), _sockfd(sockfd), _clientip(clientip), _clientport(clientport)
        {
        }
        tcp_server *_ts;
        int _sockfd;
        std::string _clientip;
        uint16_t _clientport;
    };

    class tcp_server
    {
    public:
        tcp_server(func_t func, const uint16_t &port = defaultPort) : _func(func), _port(port)
        {
        }
        void Init()
        {
            _listensock.Socket();
            _listensock.Bind(_port);
            _listensock.Listen();
        }
        static void *threadRoutine(void *args)
        {
            pthread_detach(pthread_self());
            pthreadData *pd = static_cast<pthreadData *>(args);
            pd->_ts->Server(pd->_sockfd, pd->_clientip, pd->_clientport);

            delete pd;
            return nullptr;
        }
        void Start()
        {
            while (true)
            {
                std::string clientip;
                uint16_t clientport;
                int sockfd = _listensock.Accept(&clientip, &clientport);
                if (sockfd < 0)
                    continue;

                pthread_t pid;
                pthreadData *pd = new pthreadData(this, sockfd, clientip, clientport);
                pthread_create(&pid, nullptr, threadRoutine, pd);
            }
        }
        void Server(int sockfd, const std::string &clientip, const uint16_t &clientport)
        {
            std::string inbuffer;
            while (true)
            {
                // 1.接受数据
                // 1.1 检查收到的数据是否是完整一条信息
                std::string package; // str接受完整的条信息
                int len = ReadStrPackage(sockfd, inbuffer, &package);
                if (len <= 0) // 表示还需要继续读取
                    continue;
                else//读取到数据，且知道有效载荷的长度为len
                {
                    // 1.2 去掉报头，得到有效载荷
                    std::cout<<"得到一条完整报头："<<package<<std::endl;
                    std::string effective_load = RemoveHeads(package,len);
                    std::cout<<"去掉报头后，有效载荷："<<effective_load<<std::endl;

                    // 1.3 反序列化
                    Request rq;
                    rq.Deserialization(effective_load);
                    std::cout<<"反序列化之后："<<std::endl;
                    rq.Print();
                    

                    // 2.处理任务
                    // 2.1 调用上层函数，得到结果的结构体
                    Response rs = _func(rq);
                    // 2.2 序列化
                    std::string sending_string = rs.Serialization();
                    std::cout<<"序列化之后："<<sending_string<<std::endl;
                    
                    // 3.发送数据
                    // 3.1 添加报头
                    sending_string = AddHeads(sending_string);
                    // 3.2 将数据发送到网络
                    send(sockfd, sending_string.c_str(), sending_string.size(), 0);
                }
            }
        }
        ~tcp_server() {}

    private:
        uint16_t _port;
        Sock _listensock;
        func_t _func;
    };
}